
import 'package:analyzer/dart/element/element.dart';
import 'package:build/src/builder/build_step.dart';
import 'package:source_gen/source_gen.dart';
import 'package:source_gen/src/utils.dart';
import 'package:sqflite/orm/data_class.dart';
import 'package:analyzer/src/dart/constant/value.dart';

class SqlitexDatabaseGenerator extends GeneratorForAnnotation<SqlitexDatabase> {

  @override
  generateForAnnotatedElement(Element element, ConstantReader annotation, BuildStep buildStep) async {
    if(element is! ClassElement) {
      throw InvalidGenerationSourceError("@SqlitexDatabase can only be applied to class");
    }
    final list = annotation.read('tables').listValue;
    if(list.isEmpty) {
      throw InvalidGenerationSourceError("@SqlitexDatabase tables can not be empty");
    }

    String className = element.displayName;
    String path = buildStep.inputId.path;
    String out = buildStep.allowedOutputs.first.path;
    print("//$className //$path  $out");

    final asset = buildStep.inputId;
    final outputId = buildStep.allowedOutputs.first;
    final partOfUri = uriOfPartial(element.library, asset, outputId);
    String content = _generateClass(list, partOfUri);
    return content;
  }

  _generateClass(List list, String partOfUri) {
    final contentBuffer = StringBuffer();
    contentBuffer.writeln('// GENERATED CODE - DO NOT MODIFY BY HAND');
    contentBuffer.writeln('part of \'$partOfUri\';');
    contentBuffer.writeln('abstract class _\$AppDatabase extends SqliteDataBase {');
    contentBuffer.writeln('');

    List tables = [];
    List types = [];
    for(var i = 0; i < list.length; i++) {
      final table = list[i] as DartObjectImpl;
      final name = table.state.toString().replaceFirst('*', '');
      final tableClass = '${name.substring(0,1).toLowerCase()}${name.substring(1)}';
      tables.add(tableClass);
      types.add(name);
      contentBuffer.writeln('final $name $tableClass = \$$name();');
    }

    contentBuffer.writeln('@override');
    contentBuffer.writeln('List<Table> get tables => $tables;\n');

    contentBuffer.writeln('@override');
    contentBuffer.writeln('Table getTableInfo(Type clazz){');
    contentBuffer.writeln('switch(clazz){');
    for(var i = 0; i < types.length; i++) {
      final name = types[i];
      final tableClass = tables[i];
      contentBuffer.writeln('case $name: return $tableClass;');
    }
    contentBuffer.writeln('default:  throw Exception(\'Cannot getTableInfo by class \$clazz\');');
    contentBuffer.writeln('}');
    contentBuffer.writeln('}');

    contentBuffer.writeln('}');
    return contentBuffer.toString();
  }
}